package veilingService;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import veilingDomein.Categorie;
import veilingDomein.Factuur;
import veilingDomein.FactuurRegel;
import veilingDomein.Media;
import veilingDomein.User;
import veilingDomein.Veiling;
import actions.visitors.VeilingLijstItem;

public class VeilingService implements IVeilingService {

	DBController db = new DBController();

	public ArrayList<Veiling> veilingen = new ArrayList<Veiling>();

	public VeilingService() {
		/*
		 * Gebruikers in de database zijn: Username: Beheerder Password:
		 * Beheerder123 Username: JanSte Password: JanSte123
		 */
	}

	public void init() {

	}

	@Override
	public ArrayList<Veiling> haalVeilingenop() {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		Date startDatum = new Date();
		Date eindDatum = new Date();
		try {
			stmt = con.createStatement();
			rs = stmt
					.executeQuery("SELECT * FROM goed g, veiling v where v.goed_id = g.goed_id");
			veilingen.clear();
			while (rs.next()) {
				int id = rs.getInt("gebruiker_id");
				startDatum = rs.getDate("startdatum");
				eindDatum = rs.getDate("einddatum");
				Date currentDate = new Date();
				boolean open = false;
				if (currentDate.after(startDatum)
						&& currentDate.before(eindDatum)) {
					open = true;
				}
				Categorie cat = ServiceProvider.getBiedingService()
						.haalCategorieIdOp(rs.getInt("categorie_id"));
				Veiling veiling = new Veiling(startDatum, eindDatum,
						rs.getInt("minimumbedrag"), open,
						rs.getString("titel"), cat,
						rs.getString("beschrijving"), id,
						rs.getInt("veiling_id"));
				veilingen.add(veiling);
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();
		return veilingen;
	}

	@Override
	public List<Veiling> getVeilingenByUser(User u) {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		Date startDatum = new Date();
		Date eindDatum = new Date();
		ArrayList<Veiling> mijnVeilingen = new ArrayList<Veiling>();
		try {
			stmt = con.createStatement();
			rs = stmt
					.executeQuery("SELECT * FROM goed g, veiling v where v.goed_id = g.goed_id and g.gebruiker_id = "
							+ u.getId());
			while (rs.next()) {
				startDatum = rs.getDate("startdatum");
				eindDatum = rs.getDate("einddatum");
				Date currentDate = new Date();
				boolean open = false;
				if (currentDate.after(startDatum)
						&& currentDate.before(eindDatum)) {
					open = true;
				}
				Categorie cat = ServiceProvider.getBiedingService()
						.haalCategorieIdOp(rs.getInt("categorie_id"));
				Veiling veiling = new Veiling(startDatum, eindDatum,
						rs.getInt("minimumbedrag"), open,
						rs.getString("titel"), cat,
						rs.getString("beschrijving"),
						rs.getInt("gebruiker_id"), rs.getInt("veiling_id"));
				mijnVeilingen.add(veiling);
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();
		return mijnVeilingen;
	}

	@Override
	public Veiling getVeilingByID(int id) {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		Date startDatum = new Date();
		Date eindDatum = new Date();
		Veiling veiling = null;
		try {
			stmt = con.createStatement();
			rs = stmt
					.executeQuery("SELECT * FROM goed g, veiling v where v.goed_id = g.goed_id and v.veiling_id = "
							+ id);
			while (rs.next()) {
				startDatum = rs.getTimestamp("startdatum");
				eindDatum = rs.getTimestamp("einddatum");
				Date currentDate = new Date();
				boolean open = false;
				if (currentDate.after(startDatum)
						&& currentDate.before(eindDatum)) {
					open = true;
				}
				Categorie cat = ServiceProvider.getBiedingService()
						.haalCategorieIdOp(rs.getInt("categorie_id"));
				veiling = new Veiling(startDatum, eindDatum,
						rs.getInt("minimumbedrag"), open,
						rs.getString("titel"), cat,
						rs.getString("beschrijving"),
						rs.getInt("gebruiker_id"), rs.getInt("goed_id"));
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();

		return veiling;
	}

	@Override
	public void getMediaBijVeiling(Veiling veiling) {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		Media media = null;
		try {
			stmt = con.createStatement();
			rs = stmt.executeQuery("SELECT * FROM media where veiling_id = "
					+ veiling.getVeilingId());
			while (rs.next()) {
				media = new Media();
				media.setNaam(rs.getString("naam"));
				media.setSoort(rs.getString("soort"));
				veiling.addMedia(media);
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();
	}

	// Het totaal aantal records van openstaande veilingen binnen het
	// zoekresultaat. Hier kan het aantal pagina's voor weergave uit berekend
	// worden.
	@Override
	public int zoekVeilingenCount(String zoekwoord, String catnaam, int min,
			int max) {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		int totaal = 0;
		try {
			stmt = con.createStatement();
			rs = stmt
					.executeQuery("select count(*) as totaal from table(zoek.titel('"
							+ zoekwoord
							+ "','"
							+ catnaam
							+ "',"
							+ min
							+ ","
							+ max + ")) where einddatum > sysdate");
			if (rs.next()) {
				totaal = rs.getInt("totaal");
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();
		return totaal;
	}

	// Zoeken op titel (alleen openstaande veilingen worden nu teruggegeven)
	// Het testen of een veiling open is of niet moet nog uit de java code
	// gehaald worden
	@Override
	public ArrayList<VeilingLijstItem> zoekVeilingen(String zoekwoord,
			String catnaam, int min, int max, int rownumStart, int rownumEind,
			String sorterenOp) {
		// Limiteer het aantal veilingen die per keer opgehaald kunnen worden
		// (max = 100)
		if ((rownumEind - rownumStart) >= 100) {
			rownumEind = rownumStart + 99;
		}
		boolean sorteerMatch = false;
		String[] sorteerOpties = { "titel", "startprijs", "laatste_bod",
				"einddatum", "categorie", "aantal_biedingen", "startdatum",
				"foto_url", "veiling_id" };
		for (int i = 0; i < sorteerOpties.length; i++) {
			if (sorterenOp.equals(sorteerOpties[i])) {
				sorteerMatch = true;
			}
		}

		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		VeilingLijstItem vli;
		ArrayList<VeilingLijstItem> vliLijst = new ArrayList<VeilingLijstItem>();
		try {

			stmt = con.createStatement();
			String query;
			if (sorteerMatch) {
				// Kijk of datatype van kolom tekst is, anders werkt de query
				// samen met de lower() functie niet lekker
				if (sorterenOp.equals("titel")
						|| sorterenOp.equals("categorie")
						|| sorterenOp.equals("foto_url")) {
					query = "select * from (select rownum rnum, a.* from (select * from table(zoek.titel('"
							+ zoekwoord
							+ "','"
							+ catnaam
							+ "',"
							+ min
							+ ","
							+ max
							+ ")) where einddatum > sysdate order by lower("
							+ sorterenOp
							+ ")) a where rownum <= "
							+ rownumEind
							+ ") where rnum >= " + rownumStart + "";
				} else {
					query = "select * from (select rownum rnum, a.* from (select * from table(zoek.titel('"
							+ zoekwoord
							+ "','"
							+ catnaam
							+ "',"
							+ min
							+ ","
							+ max
							+ ")) where einddatum > sysdate order by "
							+ sorterenOp
							+ ") a where rownum <= "
							+ rownumEind
							+ ") where rnum >= " + rownumStart + "";
				}
			} else {
				query = "select * from (select rownum rnum, a.* from (select * from table(zoek.titel('"
						+ zoekwoord
						+ "','"
						+ catnaam
						+ "',"
						+ min
						+ ","
						+ max
						+ ")) where einddatum > sysdate) a where rownum <= "
						+ rownumEind + ") where rnum >= " + rownumStart + "";
			}
			rs = stmt.executeQuery(query);
			while (rs.next()) {

				Date currentDate = new Date();
				Date startDatum = rs.getTimestamp("startdatum");
				Date eindDatum = rs.getTimestamp("einddatum");
				boolean open = false;
				System.out.println("cur: " + currentDate + ", start: "
						+ startDatum + ", eind: " + eindDatum);
				if (currentDate.after(startDatum)
						&& currentDate.before(eindDatum)) {
					open = true;
				}
				vli = new VeilingLijstItem(rs.getString("titel"),
						rs.getString("categorie"), rs.getString("foto_url"),
						rs.getInt("veiling_id"), rs.getInt("aantal_biedingen"),
						rs.getInt("laatste_bod"), startDatum, eindDatum,
						open, rs.getInt("startprijs"));
				vliLijst.add(vli);
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();
		return vliLijst;
	}

	// Zoeken op titel en beschrijving (alleen openstaande veilingen worden nu
	// teruggegeven)
	// Het testen of een veiling open is of niet moet nog uit de java code
	// gehaald worden

	@Override
	public ArrayList<VeilingLijstItem> zoekVeilingenTitelEnBeschrijving(
			String zoekwoord, String catnaam, int min, int max,
			int rownumStart, int rownumEind, String sorterenOp) {
		// Limiteer het aantal veilingen die per keer opgehaald kunnen worden
		// (max = 100)
		if ((rownumEind - rownumStart) >= 100) {
			rownumEind = rownumStart + 99;
		}
		boolean sorteerMatch = false;
		String[] sorteerOpties = { "titel", "startprijs", "laatste_bod",
				"einddatum", "categorie", "aantal_biedingen", "startdatum",
				"foto_url", "veiling_id" };
		for (int i = 0; i < sorteerOpties.length; i++) {
			if (sorterenOp.equals(sorteerOpties[i])) {
				sorteerMatch = true;
			}
		}

		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		VeilingLijstItem vli;
		ArrayList<VeilingLijstItem> vliLijst = new ArrayList<VeilingLijstItem>();
		try {

			stmt = con.createStatement();
			String query;
			if (sorteerMatch) {
				// Kijk of datatype van kolom tekst is, anders werkt de query
				// samen met de lower() functie niet lekker
				if (sorterenOp.equals("titel")
						|| sorterenOp.equals("categorie")
						|| sorterenOp.equals("foto_url")) {
					query = "select * from (select rownum rnum, a.* from (select * from table(zoek.titel_en_beschrijving('"
							+ zoekwoord
							+ "','"
							+ catnaam
							+ "',"
							+ min
							+ ","
							+ max
							+ ")) where einddatum > sysdate order by lower("
							+ sorterenOp
							+ ")) a where rownum <= "
							+ rownumEind
							+ ") where rnum >= " + rownumStart + "";
				} else {
					query = "select * from (select rownum rnum, a.* from (select * from table(zoek.titel_en_beschrijving('"
							+ zoekwoord
							+ "','"
							+ catnaam
							+ "',"
							+ min
							+ ","
							+ max
							+ ")) where einddatum > sysdate order by "
							+ sorterenOp
							+ ") a where rownum <= "
							+ rownumEind
							+ ") where rnum >= " + rownumStart + "";
				}
			} else {
				query = "select * from (select rownum rnum, a.* from (select * from table(zoek.titel_en_beschrijving('"
						+ zoekwoord
						+ "','"
						+ catnaam
						+ "',"
						+ min
						+ ","
						+ max
						+ ")) where einddatum > sysdate) a where rownum <= "
						+ rownumEind + ") where rnum >= " + rownumStart + "";
			}
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				Date currentDate = new Date();
				Date startDatum = rs.getDate("startdatum");
				Date eindDatum = rs.getDate("einddatum");
				boolean open = false;
				if (currentDate.after(startDatum)
						&& currentDate.before(eindDatum)) {
					open = true;
				}
				vli = new VeilingLijstItem(rs.getString("titel"),
						rs.getString("categorie"), rs.getString("foto_url"),
						rs.getInt("veiling_id"), rs.getInt("aantal_biedingen"),
						rs.getInt("laatste_bod"), startDatum, eindDatum,
						open, rs.getInt("startprijs"));
				vliLijst.add(vli);
			}
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}
		db.closeConnection();
		return vliLijst;
	}

	@Override
	public void schrijfVeilingWeg(Veiling veiling) {
		try {
			PreparedStatement pst = null;
			Connection con = db.connect();
			int newGoedId = ServiceProvider.getBiedingService().getNewGoedId();
			// Execute an SQL query, get a ResultSet
			String queryGoed = "INSERT INTO goed values(?, ?, ?, ?, ?)";
			String queryVeiling = "INSERT INTO veiling values(?, ?, ?, ?, ?, ?)";
			pst = con.prepareStatement(queryGoed);
			pst.setInt(1, newGoedId);
			pst.setInt(2, veiling.getVeiler().getId());
			pst.setInt(3, veiling.getCategorie().getCategorieId());
			pst.setString(4, veiling.getNaam());
			pst.setString(5, veiling.getBeschrijving());
			pst.executeUpdate();
			pst.close();

			pst = con.prepareStatement(queryVeiling);
			pst.setInt(1, veiling.getVeilingId());
			pst.setInt(2, newGoedId);
			pst.setTimestamp(3, new java.sql.Timestamp(veiling.getStartDatum()
					.getTime()));
			pst.setTimestamp(4, new java.sql.Timestamp(veiling.getSluitDatum()
					.getTime()));
			pst.setInt(5, veiling.getMinimumBedrag());
			pst.setInt(6, 1);
			pst.executeUpdate();
			pst.close();

			if (veiling.getMediaLijst().size() > 0) {
				int newMediaId = getNewMediaId();
				for (Media media : veiling.getMediaLijst()) {
					String query = "INSERT INTO media values(?, ?, ?, ?)";
					pst = con.prepareStatement(query);
					pst.setInt(1, newMediaId++);
					pst.setInt(2, veiling.getVeilingId());
					pst.setString(3, media.getNaam());
					pst.setString(4, media.getSoort());
					pst.executeUpdate();
					pst.close();
				}
			}
			con.close();
		} catch (SQLException e) {
			System.out.println("SQLException caught: " + e.getMessage());
		}

	}

	@Override
	public int getNewVeilingId() {
		Connection con = db.connect();
		int id = 0;
		try {
			Statement stmt = con.createStatement();
			ResultSet rs = stmt
					.executeQuery("SELECT max(goed_id) as id FROM veiling");
			while (rs.next()) {
				id = rs.getInt(1);
			}

		} catch (SQLException e) {
			System.out.println(e);
		}
		db.closeConnection();
		return ++id;
	}

	@Override
	public int getAantalVeilingen() {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		int aantal = 0;

		try {
			String query = "SELECT count(*) as aantal FROM veiling";
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				aantal = rs.getInt("AANTAL");
			}
			db.closeConnection();
		} catch (SQLException e) {
			e.printStackTrace();

		}
		return aantal;
	}

	@Override
	public int getAantalOpenVeilingen() {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		int aantal = 0;

		try {
			String query = "SELECT count(*) as aantal FROM veiling where eindDatum > SYSDATE";
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				aantal = rs.getInt("AANTAL");
			}
			db.closeConnection();
		} catch (SQLException e) {
			e.printStackTrace();

		}
		return aantal;
	}

	@Override
	public int getAantalVeilingenPerGebruiker(int userid) {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		int aantal = 0;

		try {
			String query = "SELECT count(*) as aantal from goed where gebruiker_id = "
					+ userid;
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				aantal = rs.getInt("aantal");
			}
			db.closeConnection();
		} catch (SQLException e) {
			e.printStackTrace();

		}
		return aantal;
	}

	@Override
	public int getNewMediaId() {
		Connection con = db.connect();
		int id = 0;
		try {
			Statement stmt = con.createStatement();
			ResultSet rs = stmt
					.executeQuery("SELECT max(media_id) as id FROM media");
			while (rs.next()) {
				id = rs.getInt(1);
			}

		} catch (SQLException e) {
			System.out.println(e);
		}
		db.closeConnection();
		return ++id;
	}

	@Override
	public void kredietFactuurToevoegen(User user, int aantal) {
		System.out.println("Krediet factuur aanmaken :)");
		Connection conn = db.connect();
		Statement stmt = null;
		String sql = "INSERT INTO kredietfactuur VALUES(" + getNewFactuurId()
				+ ", " + user.getId() + ", 0, " + aantal + ", sysdate)";
		try {
			stmt = conn.createStatement();
			stmt.execute(sql);
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			System.out.println(e);
		}
		db.closeConnection();

	}

	@Override
	public int getNewFactuurId() {
		Connection con = db.connect();
		int id = 0;
		try {
			Statement stmt = con.createStatement();
			ResultSet rs = stmt
					.executeQuery("SELECT max(kredietfactuur_id) as id FROM kredietfactuur");
			while (rs.next()) {
				id = rs.getInt(1);
			}

		} catch (SQLException e) {
			System.out.println(e);
		}
		db.closeConnection();
		return ++id;
	}

	@Override
	public void updateVeiling(Veiling v) {
		Connection con = db.connect();
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			stmt.executeQuery("UPDATE GOED SET beschrijving ='"
					+ v.getBeschrijving()
					+ "', titel = '"
					+ v.getNaam()
					+ "' WHERE goed_id = (SELECT goed_id from veiling where veiling_id = "
					+ v.getVeilingId() + ")");
		} catch (SQLException e) {
			System.out.println(e);
		}
	}

	@Override
	public int getAantalVeilingenPerCategorie(int categorieid) {
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		int aantal = 0;

		try {
			String query = "SELECT count(*) as aantal from goed WHERE categorie_id = "
					+ categorieid;
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				aantal = rs.getInt("aantal");
			}
			db.closeConnection();
		} catch (SQLException e) {
			e.printStackTrace();

		}
		return aantal;
	}

	@Override
	public void sluitVeiling(int id) {
		Connection con = db.connect();
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			stmt.executeQuery("UPDATE veiling SET isopen = 0 WHERE veiling_id = " 
					+ id);
		}catch(SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	@Override
	public ArrayList<Factuur> getFacturen(User u) {
		ArrayList<Factuur> facturen = new ArrayList<Factuur>();
		ArrayList<FactuurRegel> factuurregels = new ArrayList<FactuurRegel>();
		Factuur factuur;
		FactuurRegel factuurregel;
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;

		try {
			String query = "SELECT * from factuur f, factuurregel fr where gebruiker_id =" + u.getId() + "and f.factuur_id = fr.factuur_id";
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				factuurregel = new FactuurRegel(rs.getInt("aantal"), rs.getInt("bedrag"), rs.getDouble("btw"), getVeilingByID(rs.getInt("veiling_id")));
				factuurregels.add(factuurregel);
				factuur = new Factuur(rs.getInt("factuur_id"), rs.getDate("DATUM"), factuurregels);
				facturen.add(factuur);
			}
			db.closeConnection();
		} catch (SQLException e) {
			e.printStackTrace();

		}
		return facturen;
	}
	
	@Override
	public ArrayList<FactuurRegel> getFactuurRegels(Factuur factuur) {

		ArrayList<FactuurRegel> factuurregels = new ArrayList<FactuurRegel>();
		FactuurRegel factuurregel;
		Connection con = db.connect();
		Statement stmt = null;
		ResultSet rs = null;
		
		try {
			String query = "SELECT * from factuurregel fr where factuur_id =" + factuur.getId();
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			while (rs.next()) {
				factuurregel = new FactuurRegel(rs.getInt("aantal"), rs.getInt("bedrag"), rs.getDouble("btw"), getVeilingByID(rs.getInt("veiling_id")));
				factuurregels.add(factuurregel);
			}
			db.closeConnection();
		} catch (SQLException e) {
			e.printStackTrace();

		}
		return factuurregels;
		
		
	}
	
}
